﻿using CXZD.Bll;
using CXZD.Bll.Projects;
using CXZD.Bll.Projects.File;
using CXZD.DataModel;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using CXZD.Bll.Projects.Config;
using CXZD.Common;
using RestSharp;
using Newtonsoft.Json;
using System.Web;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Threading.Tasks;

/*
 程序员：CZB
 时间：2019年2月20日
*/
namespace CXZD.Areas.API.Controllers.Projects.File
{
    /// <summary>
    /// 资料文件夹
    /// </summary>
    [RoutePrefix("api/{projectID}/ProjectFileClass")]
    public class ProjectFileClassController : BaseApiController
    {
        private readonly ProjectFileClassBll _ProjectFileClassBll = new ProjectFileClassBll();
        private readonly ProjectInfoBll _ProjectInfoBll = new ProjectInfoBll();
        private readonly ProjectWorkNavBll _ProjectWorkNavBll = new ProjectWorkNavBll();
        private readonly SysUserBll _SysUserBll = new SysUserBll();
        private readonly ActionLogBll _ActionLogBll = new ActionLogBll();
        readonly SysAnnexBll _SysAnnexBll = new SysAnnexBll();
        readonly ProjectFileBll _ProjectFileBll = new ProjectFileBll();
        readonly ProjectArchiveBll _ProjectArchiveBll = new ProjectArchiveBll();

        /// <summary>
        /// 数据获取
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="where">查询条件</param>
        /// <param name="order">排序</param>
        /// <param name="skip">跳过</param>
        /// <param name="take">前几</param>
        /// <returns></returns>
        [HttpGet, Route("")]
        public IEnumerable<dynamic> Get([FromUri] Guid projectID,
            [FromUri] string where = "",
            [FromUri] string order = "Sort asc",
            [FromUri] int skip = 0,
            [FromUri] int take = int.MaxValue)
        {
            where = string.Format("ProjectInfo.ID=GUID(\"{0}\") {1}", projectID, string.IsNullOrEmpty(where) ? "" : " and " + where);
            var list = _ProjectFileClassBll.All.Where(@where).Where(u => u.Recycle == false)
                // 权限验证  注释时间：2019-9-5 项目内默认加载会调用到
                //                    .Privilege(new string[] {"PROJECT_FILECLASS"}, UserID, projectID)
                .OrderBy(order).Skip(skip).Take(take)
                .Include(d => d.Parent).Include(d => d.Children).Select(toResultData).AsNoTracking();/*2019.12.12 zpp toResultData*/
            return list;
        }

        /// <summary>
        /// 获取文件夹（无权限验证，只包含ID 名称  子父级）
        /// </summary>
        /// <param name="projectID"></param>
        /// <param name="where"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        [HttpGet, Route("GetList")]
        public IEnumerable<dynamic> GetList([FromUri] Guid projectID,
           [FromUri] string where = "", [FromUri] string order = "Sort asc")
        {
            where = $"ProjectInfo.ID=GUID(\"{projectID}\") {(string.IsNullOrEmpty(@where) ? "" : " and " + @where)}";
            var list = _ProjectFileClassBll.All.Where(@where)
                .Include(d => d.Parent).Include(d => d.Children).Include(d => d.ProjectInfo).OrderBy(order).Select(
                    model => new
                    {
                        model.ID,
                        model.Name,
                        model.Sort,
                        Parent = model.Parent != null ? new { model.Parent.ID, model.Parent.Name } : null, /*父文件夹*/
                        Children = model.Children.Select(d => new { d.ID, d.Name }), /*子文件夹集合*/
                    }).AsNoTracking().ToList();
            return list;
        }

        /// <summary>
        /// 获取条件下总数
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="where">查询条件</param>
        /// <returns></returns>
        [HttpGet, Route("Count"), ProjectFilter(key = "PROJECT_DOCUMENT")]
        public int GetCount([FromUri] Guid projectID, [FromUri] string where = "")
        {
            where = string.Format("ProjectInfo.ID=GUID(\"{0}\") {1}", projectID, string.IsNullOrEmpty(where) ? "" : " and " + where);
            return _ProjectFileClassBll.All.Where(@where).Count();
        }

        /// <summary>
        /// 获取单条
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="ID">文件夹ID</param>
        /// <returns></returns>
        [HttpGet, Route("{ID}"), ProjectFilter(key = "PROJECT_DOCUMENT")]
        public dynamic GetOnly([FromUri] Guid projectID, [FromUri] Guid ID)
        {/*2019.12.12 zpp*/
            var model = _ProjectFileClassBll.GetModel(ID);
            return toResultData.Compile()(model);
        }

        /// <summary>
        /// 初始化资料文件夹
        /// </summary>
        /// <param name="projectID"></param>
        /// <returns></returns>
        [ProjectFilter(key = "PROJECT_FILECLASS_INIT")]
        public string InitFileClass([FromUri] Guid projectID)
        {
              
            var project = _ProjectInfoBll.GetModel(projectID);
            if (project == null) throw new CXZD.Common.CxosftException("项目ID错误");

            // 获取项目配置的工作菜单集合
            var workNaves = _ProjectWorkNavBll.All.Where(p => p.ProjectInfo.ID == projectID).OrderBy(s => s.Sort).ToList();

            // 获取现有的所有顶级文件夹集合
            var fileClassList = _ProjectFileClassBll.All.Where(f => f.ProjectInfo.ID == projectID).ToList();

            if (workNaves.Any())
            {
                // 递归添加方法
                CheckFileNameAndAdd(workNaves, fileClassList, projectID);
            }

            _ProjectFileClassBll.SaveChanges();
            return "资料文件初始化成功";
        }

        /// <summary>
        /// 验证子级文件夹是否存在，不存则添加
        /// </summary>
        /// <param name="workNaves">项目内的工作菜单</param>
        /// <param name="fileClassList">现有文件夹集合</param>
        /// <param name="projectID">项目ID</param>
        private void CheckFileNameAndAdd(List<ProjectWorkNav> workNaves, List<ProjectFileClass> fileClassList, Guid projectID)
        {
            Action<List<ProjectWorkNav>, ProjectFileClass> createAction = null;
            // 待插入数据库的数组集合
            var addClassList = new List<ProjectFileClass>();
            // 递归添加方法
            createAction = (roots, parent) =>
            {
                roots.ForEach(r =>
                {
                    // 查询现有文件夹
                    var old = fileClassList.FirstOrDefault(f => f.Name == r.Name && f.Parent_ID == parent?.ID);
                    if (old != null)
                    {
                        // 验证子级文件夹
                        createAction(workNaves.Where(w => w.SysProjectNave_Parent_ID == r.SysProjectNave_ID).ToList(),
                            old);
                    }
                    else
                    {
                        // 创建新的文件夹实体
                        var model = new ProjectFileClass
                        {
                            ID = Guid.NewGuid(),
                            Name = r.Name,
                            Sort = r.Sort,
                            ProjectInfo_ID = projectID,
                            Parent_ID = parent == null ? null : (Guid?)parent.ID
                        };
                        // 添加到待插入数据库的数组集合
                        addClassList.Add(model);
                        // 子级文件夹创建
                        createAction(workNaves.Where(u => u.SysProjectNave_Parent_ID == r.SysProjectNave_ID).ToList(),
                            model);
                    }
                });
            };

            // 第一次调用使用顶级工作工作菜单，且进度计划为null
            createAction(workNaves.Where(u => u.SysProjectNave_Parent_ID == null).ToList(), null);
            _ProjectFileClassBll.Add(addClassList.ToArray());
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="obj">实体数据</param>
        /// <returns></returns>
        [HttpPost, Route(""), ProjectFilter(key = "PROJECT_DOCUMENT_ADDFILE")]
        public dynamic Post([FromUri] Guid projectID, [FromBody] ProjectFileClass obj)
        {


            var project = _ProjectInfoBll.GetModel(projectID);
            if (project == null)
                throw new CXZD.Common.CxosftException("查询的项目信息不存在！");

            obj.ID = Guid.NewGuid();
            obj.ProjectInfo = project;

            if (obj.Parent != null)
            {
                obj.Parent = _ProjectFileClassBll.GetModel(obj.Parent.ID);

                if(obj.Parent.Children.Any(p=>p.Name == obj.Name&&!p.Recycle))
                    throw new CXZD.Common.CxosftException("存在同名文件夹");

                obj.Sort = obj.Parent.Children.Count > 0 ? obj.Parent.Children.Max(u => u.Sort) + 1 : 1;

            }
            else
            {
                if(_ProjectFileClassBll.All.Any(u => u.ProjectInfo.ID == projectID && u.Parent == null&&u.Name==obj.Name))
                    throw new CXZD.Common.CxosftException("存在同名文件夹");

                if (obj.Sort <= 0 && _ProjectFileClassBll.All.Any(u => u.ProjectInfo.ID == projectID && u.Parent == null))
                    obj.Sort = _ProjectFileClassBll.All.Where(u => u.ProjectInfo.ID == projectID && u.Parent == null).Max(u => u.Sort) + 1;
                else
                    obj.Sort = 0;
            }

            _ProjectFileClassBll.Add(obj);

            /*操作文件夹，父级文件夹更新时间 zpp 2019.12.12*/
            if (obj.Parent != null)
            {
                _ProjectFileClassBll.Update(obj.Parent, new Dictionary<string, object> { { "UpdatedTime", obj.CreatedTime } });
            }
            _ProjectFileClassBll.SaveChanges();

            //#region 添加日志 zpp 2020.1.7
            //_ActionLogBll.AddActionLog<ProjectFileClass>(
            //    $"添加了一个文件夹《{obj.Name}》", LogTypeEnum.操作日志, LevelE num.Project, obj.NavToken, "项目资料",
            //    projectID, obj.ProjectInfo?.Name, "ProjectFileClass", obj.ID.ToString(), obj);
            //#endregion
            #region 添加日志 djx 2020.7.21

            var projectMenu = _ProjectWorkNavBll.All.FirstOrDefault(s =>
                 s.ProjectInfo_ID == projectID && s.NavToken == obj.NavToken && s.ProjectState == obj.ProjectState);// made：djx time：2020.7.13 补充日志信息
            _ActionLogBll.AddActionLog<ProjectFileClass>(
             projectMenu != null ?
               $" {projectMenu.Name}菜单下，新建了一个文件夹《{obj.Name}》" : $" 新建了一个文件夹《{obj.Name}》",
               LogTypeEnum.操作日志, LevelEnum.Project, obj.NavToken, "项目资料", projectID, project.Name,
               "ProjectFileClass", obj.ID.ToString(), obj, null, 0, project.Organization_ID);
            #endregion
            return toResultData.Compile()(obj);/*2019.12.12 zpp*/
        }

        /// <summary>
        /// 上传文件夹的实体类
        /// </summary>
        public class model
        {
            /// <summary>
            /// 传入的完整路径
            /// </summary>
            public string webkitRelativePath { get; set; }
            /// <summary>
            /// 文件名
            /// </summary>
            public string name { get; set; }
            /// <summary>
            /// 文件大小
            /// </summary>
            public int size { get; set; }
            /// <summary>
            /// 最后修改时间
            /// </summary>
            public DateTime lastModifiedDate { get; set; }
        }


        /// <summary>
        /// 上传单个文件和文件夹API
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="FileClassID">文件夹放入的文件夹ID，如果没有传"00000000-0000-0000-0000-000000000000"</param>
        /// 添加完之后，注意返回的数据。
        /// <returns></returns>
        [HttpPost, Route("AddFileAndFileClass/{FileClassID}")]
        public dynamic AddFileAndFileClass([FromUri] Guid projectID, [FromUri] Guid FileClassID)
        {
            //obj: {"webkitRelativePath":string}
            #region 数据处理及验证
            var project = _ProjectInfoBll.GetModel(projectID);
            if (project == null)
                throw new CXZD.Common.CxosftException("查询的项目信息不存在！");

            //父级文件夹
            var parentFileClass = _ProjectFileClassBll.GetModel(FileClassID);
            if (FileClassID != Guid.Empty && parentFileClass == null && parentFileClass.Recycle == true)
                throw new CXZD.Common.CxosftException("父级文件夹不存在！");

            //最后的文件夹
            ProjectFileClass lastFileClass = null;

            //是否为顶级文件夹
            var isTop = parentFileClass == null;
            //获取父文件夹路径
            var parentFileClassPath = _ProjectFileClassBll.getPathFromObj(parentFileClass);

            //数据处理
            var obj = HttpContext.Current.Request.Form["obj"].ToString();
            if (obj == "") throw new CXZD.Common.CxosftException("传入的数据为空！");
            var data = Newtonsoft.Json.JsonConvert.DeserializeObject<model>(obj);

            #region 附件处理
            var file = HttpContext.Current.Request.Files[0];
            var md5 = file.InputStream.GetMd5Code();
            var filename = HttpContext.Current.Server.MapPath($@"/Upload/{DateTime.Now:yyyyMMdd}/{md5}/{data.name}");
            var Annex = _SysAnnexBll.Upload(file.InputStream, filename);
            List<dynamic> dyList = new List<dynamic>();
            dyList.Add(new
            {
                FileID = Guid.NewGuid(),
                FileName = Annex.FileName,
                Length = Annex.Length,
                ContentType = Annex.ContentType,
                Suffix = Annex.Suffix,
                MD5Code = Annex.MD5Code
            });
            var AnnexFile = Newtonsoft.Json.JsonConvert.SerializeObject(dyList);
            #endregion 附件处理

            #endregion 数据处理及验证

            if (true)
            {
                var folderNames = System.IO.Path.GetDirectoryName(data.webkitRelativePath.Replace('/','\\')).Split('\\');
                if (folderNames.Count() <= 0)
                    throw new CXZD.Common.CxosftException("前端传入的路径错误！");

                //保证如果顶级文件夹不为空，作为传入的参数
                int arrayMaxIndex = folderNames.Length - 1;
                ProjectFileClass topFileClass = null;

                topFileClass = isTop ? _ProjectFileClassBll.All.FirstOrDefault(p => p.ProjectInfo_ID == projectID && p.Name == folderNames.FirstOrDefault() && p.Recycle == false)
                                     : parentFileClass;

                #region add 递归添加文件夹
                int index = -1;//确实应该从0开始
                Action<ProjectFileClass> add = null;
                add = (projectFileClass) =>
                {
                    //数组索引
                    index++;
                    
                    //参数检测,及索引检测
                    if (projectFileClass == null)
                    {
                        //索引检测（参数与索引不能同时错误，也不会同时错误）
                        if (index > arrayMaxIndex) 
                            throw new CXZD.Common.CxosftException("上传文件夹：参数为空，索引错误");

                        projectFileClass = new ProjectFileClass();
                        projectFileClass.ID = Guid.NewGuid();
                        projectFileClass.Name = folderNames[index];
                        projectFileClass.CreatedBy = UserID;
                        projectFileClass.ProjectInfo_ID = projectID;
                        projectFileClass.CreatedTime = DateTime.Now;

                        _ProjectFileClassBll.Add(projectFileClass);
                    }

                    //最后一个文件夹为归档文件夹,且停止递归
                    if (index > arrayMaxIndex)
                    { 
                        lastFileClass = projectFileClass;
                        return;
                    }

                    ProjectFileClass sonFileClass=null;
                    //当前文件夹是否存在
                    if (isTop)
                    {
                        sonFileClass = index == 0
                                            ? projectFileClass : (projectFileClass.Children == null
                                            ? null : projectFileClass.Children.FirstOrDefault(p => p.Name == folderNames[index]));
                    }
                    else 
                    {
                        sonFileClass = projectFileClass.Children.FirstOrDefault(p => p.Name == folderNames[index]&&!p.Recycle);
                    }

                    //如果子文件夹不存在，则添加文件夹
                    if (sonFileClass == null)
                    {
                        sonFileClass = new ProjectFileClass();
                        sonFileClass.ID = Guid.NewGuid();
                        sonFileClass.Name = folderNames[index];
                        sonFileClass.CreatedBy = UserID;
                        sonFileClass.Parent_ID = (Guid?)projectFileClass.ID;
                        sonFileClass.ProjectInfo_ID = projectID;
                        sonFileClass.CreatedTime = DateTime.Now;
                        _ProjectFileClassBll.Add(sonFileClass);
                        //add(sonFileClass);
                    }

                    //else //如果子文件夹存在,则继续递归
                    add(sonFileClass);
                };
                #endregion 递归添加文件夹

                //入口
                add(topFileClass);
            }

            #region 添加文件到文件夹
            var ProjectFile = new ProjectFile
            {
                ID = Guid.NewGuid(),
                Name = System.IO.Path.GetFileNameWithoutExtension(data.name),
                Length = Annex.Length,
                AnnexFile = AnnexFile,
                ProjectInfo_ID = projectID,
                ProjectFileClass = lastFileClass ?? null,
                CreatedBy = UserID,
                CreatedTime = DateTime.Now
            };

            _ProjectFileBll.Add(ProjectFile);
            #endregion 添加文件到文件夹

            //保存
            _ProjectFileBll.SaveChanges();

            return "添加成功";
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="ID">ID</param>
        /// <param name="obj">实体数据</param>
        /// <returns></returns>
        [HttpPut, Route("{ID}"), ProjectFilter(key = "PROJECT_DOCUMENT_EDITFILE")]
        public dynamic Put([FromUri] Guid projectID, [FromUri] Guid ID, [FromBody] ProjectFileClass obj)
        {
            var project = _ProjectInfoBll.GetModel(projectID);
            if (project == null)
                throw new CXZD.Common.CxosftException("查询的项目信息不存在！");

            //Parent=null时，更新异常的解决方案.Include(u => u.Parent)
            var model = _ProjectFileClassBll.All.Include(u => u.Parent).FirstOrDefault(u => u.ID == ID);
            if (model == null)
                throw new CXZD.Common.CxosftException("查询的数据不存在！");

            _SysUserBll.PrivilegeFile("FILE_UPDATE", UserID, projectID, model.ID);

            _ProjectFileClassBll.Update(model, GetRequestParms());
            if (obj.Parent != null)
            {
                var res = model.Children.SelectMany(s => s.Children).Concat(model.Children).ToList();
                res.Add(model);

                if (res.Select(S => S.ID).Contains(obj.Parent.ID))
                {
                    throw new CXZD.Common.CxosftException("移动失败，请勿移动到子目录下!");
                }

                model.Parent = _ProjectFileClassBll.GetModel(obj.Parent.ID);
            }
            else
            {
                model.Parent = null;
            }

            /*操作文件夹，父级文件夹更新时间 zpp 2019.12.12*/
            if (model.Parent != null)
            {
                _ProjectFileClassBll.Update(model.Parent,
                    new Dictionary<string, object> { { "UpdatedTime", model.UpdatedTime } });
            }

            //#region 添加日志 zpp 2020.1.7
            //_ActionLogBll.AddActionLog<ProjectFileClass>(
            //    $"修改了一个文件夹《{model.Name}》", LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料",
            //    projectID, model.ProjectInfo?.Name, "ProjectFileClass", model.ID.ToString(), model);
            //#endregion
            #region 添加日志 djx 2020.7.21

            var projectMenu = _ProjectWorkNavBll.All.FirstOrDefault(s =>
                 s.ProjectInfo_ID == projectID && s.NavToken == model.NavToken && s.ProjectState == model.ProjectState);// made：djx time：2020.7.13 补充日志信息
            _ActionLogBll.AddActionLog<ProjectFileClass>(
             projectMenu != null ?
               $" {projectMenu.Name}菜单下，修改了一个文件夹《{model.Name}》" : $" 修改了一个文件夹《{model.Name}》",
               LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料", projectID, project.Name,
               "ProjectFileClass", model.ID.ToString(), model, null, 0, project.Organization_ID);
            #endregion
            _ProjectFileClassBll.SaveChanges();
            return toResultData.Compile()(model); /*2019.12.12 zpp*/
        }

        /// <summary>
        /// 关联模型、图纸、图片
        /// </summary>
        /// <param name="projectID"></param>
        /// <param name="ID"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        /// <remarks>Author: zyq  Date: 2020年3月10日</remarks>
        [HttpPut, Route("{ID}/Relation"), ProjectFilter(key = "PROJECT_DOCUMENT_RELATIONAL")]
        public dynamic Relation([FromUri] Guid projectID, [FromUri] Guid ID, [FromBody] ProjectFileClass obj)
        {
            var model = _ProjectFileClassBll.GetModel(ID);
            if (model == null) throw new CXZD.Common.CxosftException("查询的数据不存在！");


            // 判断数据是否关联的菜单  modifier:xj  Date:2020年5月12日
            if (string.IsNullOrEmpty(model.NavToken))
            {
                if (string.IsNullOrEmpty(obj.NavToken))
                    throw new CXZD.Common.CxosftException("菜单token不能为空！");
                model.NavToken = obj.NavToken;
            }

            // 关联图纸
            if (!string.IsNullOrEmpty(obj.AssociatedDrawings))
                model.AssociatedDrawings = obj.AssociatedDrawings;
            // 关联图片
            if (!string.IsNullOrEmpty(obj.AssociationImage))
                model.AssociationImage = obj.AssociationImage;
            // 关联模型
            if (!string.IsNullOrEmpty(obj.RelationComponent))
                model.RelationComponent = obj.RelationComponent;
            // 关联地图     modify by db    date:2020.5.13
            if (!string.IsNullOrEmpty(obj.AssociationMap))
                model.AssociationMap = obj.AssociationMap;

            _ProjectFileClassBll.UpdateRelation(model);
            _ProjectFileClassBll.SaveChanges();

            #region 添加日志 zpp 2020.1.7
            _ActionLogBll.AddActionLog<ProjectFileClass>(
                $"《{model.Name}》关联模型、图纸、图片", LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料",
                projectID, model.ProjectInfo?.Name, "ProjectFileClass", model.ID.ToString(), model);
            #endregion

            #region 添加模型构件关系  modify by db  date：2020.5.12
            new ProjectModelComponentBll().RelationModelComponent(projectID, obj.RelationComponent,
                model.NavToken, model.ID.ToString(), "ProjectFileClasses");
            #endregion

            return toResultData.Compile()(model);
        }

        /// <summary>
        /// 上移
        /// </summary>
        /// <param name="projectID"></param>
        /// <param name="ID"></param>
        /// add by zpp 2019.12.31
        /// <returns></returns>
        [HttpGet, Route("{ID}/MoveUp")]
        public dynamic MoveUp([FromUri] Guid projectID, [FromUri] Guid ID)
        {
            var model = _ProjectFileClassBll.GetModel(ID);
            var LevelFiles = _ProjectFileClassBll.All.Where(s => s.ProjectInfo_ID == projectID && s.Parent_ID == model.Parent_ID)
                .Select(s => new { s.ID, s.Sort }).OrderBy(s => s.Sort).AsNoTracking().ToList();

            var index = LevelFiles.FindIndex(s => s.ID == ID);
            var exFile = LevelFiles.Take(index).LastOrDefault();

            if (exFile != null)
            {
                var sort = model.Sort;
                model.Sort = exFile.Sort;

                _ProjectFileClassBll.Update(model.ID, new Dictionary<string, object>() { { "Sort", model.Sort } });/*修改上移的数据*/
                _ProjectFileClassBll.Update(exFile.ID, new Dictionary<string, object>() { { "Sort", sort } });/*修改被下移的数据*/
                _ProjectFileClassBll.SaveChanges();
            }

            return toResultData.Compile()(model);
        }

        /// <summary>
        /// 下移
        /// </summary>
        /// <param name="projectID"></param>
        /// <param name="ID"></param>
        /// add by zpp 2019.12.31
        /// <returns></returns>
        [HttpGet, Route("{ID}/MoveDown")]
        public dynamic MoveDown([FromUri] Guid projectID, [FromUri] Guid ID)
        {
            var model = _ProjectFileClassBll.GetModel(ID);
            var LevelFiles = _ProjectFileClassBll.All.Where(s => s.ProjectInfo_ID == projectID && s.Parent_ID == model.Parent_ID)
                .Select(s => new { s.ID, s.Sort }).OrderBy(s => s.Sort).AsNoTracking().ToList();

            var index = LevelFiles.FindIndex(s => s.ID == ID);
            var exFile = LevelFiles.Skip(index + 1).FirstOrDefault();

            if (exFile != null)
            {
                var sort = model.Sort;
                model.Sort = exFile.Sort;

                _ProjectFileClassBll.Update(model.ID, new Dictionary<string, object>() { { "Sort", model.Sort } });/*修改下移的数据*/
                _ProjectFileClassBll.Update(exFile.ID, new Dictionary<string, object>() { { "Sort", sort } });/*修改被上移的数据*/
                _ProjectFileClassBll.SaveChanges();
            }

            return toResultData.Compile()(model);
        }

        /// <summary>
        /// 彻底删除
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="ID">ID</param>
        /// <returns></returns>
        [HttpDelete, Route("{ID}")]
        public dynamic Delete([FromUri] Guid projectID, [FromUri] Guid ID)
        {
            var model = _ProjectFileClassBll.All.Include(s => s.Children).Include(c => c.ProjectFiles).Include(p => p.ProjectInfo)
                .FirstOrDefault(f => f.ID == ID && f.ProjectInfo.ID == projectID);

            if (model == null)
                return null;    // 前端批量删除时，提示的数据不存在提示修改； Modifier:db  2020年8月13日
            // 权限验证  不需要 xieJi 2020.5.20
            // _SysUserBll.PrivilegeFile("FILE_DELETE", UserID, projectID, model.ID);

            #region 日志：删除需提前提取数据 zpp 2020.1.8
            var projectName = model.ProjectInfo?.Name;
            var CurrentValues = _ProjectFileClassBll.DB.Entry<ProjectFileClass>(model)?.CurrentValues;
            var dic = _ActionLogBll.GetPropertyValues(CurrentValues);
            #endregion

            _ProjectFileClassBll.Delete(model);
            _ProjectFileClassBll.SaveChanges();

            #region 添加日志 zpp 2020.1.7
            _ActionLogBll.AddActionLog<ProjectFileClass>(
                $"彻底删除了一个文件夹《{model.Name}》", LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料",
                projectID, projectName, "ProjectFileClass", model.ID.ToString(), model, dic);
            #endregion

            return "删除成功！";
        }

        #region 回收站

        /// <summary>
        /// 数据进入回收站
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="ID">ID</param>
        /// <returns></returns>
        [HttpPut, Route("{ID}/Recycle")]
        public dynamic Into_Recycle([FromUri] Guid projectID, [FromUri] Guid ID)
        {
            var model = _ProjectFileClassBll.GetModel(ID);
            if (model == null)
                throw new CXZD.Common.CxosftException("查询的数据不存在！");
            /*权限验证*/
            _SysUserBll.PrivilegeFile("FILE_DELETE", UserID, projectID, model.ID);

            model.Recycle = true;
            model.RecycleTime = DateTime.Now;
            _ProjectFileClassBll.Update(model);

            /*操作文件夹，父级文件夹更新时间 zpp 2019.12.12*/
            if (model.Parent != null)
            {
                _ProjectFileClassBll.Update(model.Parent, new Dictionary<string, object> { { "UpdatedTime", model.UpdatedTime } });
            }
            _ProjectFileClassBll.SaveChanges();

            #region 添加日志 zpp 2020.1.7
            /*添加日志*/
            _ActionLogBll.AddActionLog<ProjectFileClass>(
                $"刪除了一个文件夹《{model.Name}》", LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料",
                projectID, model.ProjectInfo?.Name, "ProjectFileClass", model.ID.ToString(), model);
            #endregion

            return toResultData.Compile()(model);/*2019.12.12 zpp*/
        }

        /// <summary>
        /// 回收站数据还原
        /// </summary>
        /// <param name="projectID">项目ID</param>
        /// <param name="ID">ID</param>
        /// <returns></returns>
        [HttpPut, Route("{ID}/RecycleBack")]
        public dynamic Back_Recycle([FromUri] Guid projectID, [FromUri] Guid ID)
        {
            var model = _ProjectFileClassBll.GetModel(ID);
            if (model == null)
                throw new CXZD.Common.CxosftException("查询的数据不存在！");
            model.Recycle = false;
            model.RecycleTime = DateTime.Now;
            _ProjectFileClassBll.Update(model);

            /*操作文件夹，父级文件夹更新时间 zpp 2019.12.12*/
            if (model.Parent != null)
            {
                var parentFileClass = _ProjectFileClassBll.GetModel(model.Parent_ID);

                //author:llx date:2020.9.8 还原回收站，出现同名文件夹的处理方式
                if (parentFileClass.Children.Any(p => p.Name == model.Name))
                {
                    model.Name = model.Name + (parentFileClass.Children.Count(p => p.Name == model.Name)+1).ToString();
                }

                _ProjectFileClassBll.Update(model.Parent, new Dictionary<string, object> { { "UpdatedTime", model.UpdatedTime } });
            }
            _ProjectFileClassBll.SaveChanges();

            #region 添加日志 zpp 2020.1.7
            /*添加日志*/
            _ActionLogBll.AddActionLog<ProjectFileClass>(
                $"还原了一个文件夹《{model.Name}》", LogTypeEnum.操作日志, LevelEnum.Project, model.NavToken, "项目资料",
                projectID, model.ProjectInfo?.Name, "ProjectFileClass", model.ID.ToString(), model);
            #endregion

            return toResultData.Compile()(model);/*2019.12.12 zpp*/
        }

        #endregion


        #region 自动归档

        ///// <summary>
        ///// 自动归档
        ///// </summary>
        ///// <param name="projectID">项目ID</param>
        ///// <param name="obj">{"path":"专项咨询/设计咨询/方案设计/设计任务书编制"}</param>
        ///// <returns></returns>
        ///// auther:llx date:2020.6.16
        //[HttpPut, Route("{ID}/AutoArchive")]
        //public dynamic AutoArchiveByPath([FromUri]Guid projectID, [FromUri]Guid ID, [FromBody]JObject obj)
        //{
        //    var path = obj["path"].ToString();
        //    var tableName = obj["tableName"].ToString();

        //    string sql = "";

        //    var m = _ProjectOtherBll.GetModel(ID);
        //    if (m == null)
        //        throw new CXZD.Common.CxosftException("数据不存在！");

        //    _ProjectArchiveBll.AutoArchiveByPath(m, path);

        //    return "归档成功";
        //}

        #endregion 自动归档

        /// <summary>
        /// 返回数据 2019.12.12 zpp
        /// </summary>
        private System.Linq.Expressions.Expression<Func<ProjectFileClass, dynamic>> toResultData = model => new
        {
            model.ID,
            model.AnnexFile,
            Parent = model.Parent != null ? new { model.Parent.ID, model.Parent.Name, model.Parent.UpdatedTime } : null, /*父文件夹*/
            Children = model.Children.Select(d => new { d.ID, d.Name }), /*子文件夹集合*/
            model.Name,
            model.Recycle,
            model.RecycleTime,
            model.CreatedTime,
            model.CreatedUserInfo,
            model.UpdatedTime,
            model.UpdatedUserInfo,
            model.ProjectState,
            model.NavToken,
            model.Sort,
            HasRelationComponent = model.HasRelationComponent,
            model.HasAssociatedDrawing,
        };

    }
}
